package cn.jbit.config;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import cn.jbit.filter.PermsFilter;
import cn.jbit.realem.ShiroRealem;



/**
 * shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理
 * @author Administrator
 */
@Configuration
public class ShiroConfig {
	// 将自定义的验证方式(域)加入容器
	@Bean("shiroRealm")
	public ShiroRealem shiroRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher) {
		ShiroRealem realem = new ShiroRealem();
		realem.setAuthorizationCachingEnabled(false);
		realem.setCredentialsMatcher(matcher);
		return realem;
	}
	// 权限管理，配置主要是使用自定义的Realm的管理认证
	//定义安全管理器securityManager,注入自定义的realm
	@Bean
	public SecurityManager securityManager(@Qualifier("shiroRealm") ShiroRealem shiroRealm) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(shiroRealm);
		return securityManager;
	}
	 /**
	     * 密码校验规则HashedCredentialsMatcher
	     * 这个类是为了对密码进行编码的 ,
	     * 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
	     * 这个类也负责对form里输入的密码进行编码
	     * 处理认证匹配处理器：如果自定义需要实现继承HashedCredentialsMatcher
	     * 创建hashedCredentialsMatcher 用来匹配加密名称和加密次数
	     * 散列凭证匹配器->HashedCredentialsMatcher
      */
	@Bean("hashedCredentialsMatcher")
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
		// 指定加密方式为MD5
		credentialsMatcher.setHashAlgorithmName("md5");
		// 加密次数
		credentialsMatcher.setHashIterations(10);
		//setStoredCredentialsHexEncoded 设置已编码的存储凭证
		credentialsMatcher.setStoredCredentialsHexEncoded(true);
		return credentialsMatcher;
	}
	// Filter工厂，设置对应的过滤条件和跳转条件
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager,
			@Qualifier("permsFilter")PermsFilter permsFilter) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		Map<String, Filter> filters = new HashMap<String,Filter>();
		filters.put("perms", permsFilter);
		shiroFilterFactoryBean.setFilters(filters);
		Map<String, String> map = new HashMap<String, String>();
		// 注销 key: 动作 value:视图名称
//		map.put("/logout", "logout");

		// 对所有用户认证 authc 需要认证
//		map.put("/**", "authc");1
		// 允许匿名访问 anon 表示不登陆也可以访问
		map.put("/static/**", "anon");
		map.put("/css/**", "anon");
		map.put("/js/**", "anon");
		map.put("/img/**", "anon");
		
		//注册页面请求
		map.put("/reg", "anon");
		
		// 分页查询数据 根据用户名字模糊查询，只有root权限用户才能进入
		map.put("/**/user_page_list", "perms[root]");
		
		//异常
		map.put("/**/404","anon");
		
		//用户登录验证
		map.put("/user_login","anon");
		map.put("/**/js/**", "anon");
		map.put("/**/img/**", "anon");
		map.put("/**/reg", "anon");
		map.put("/**/user_page_list", "perms[root]");// 分页查询数据 根据用户名字模糊查询，只有root权限用户才能进入
		map.put("/**/login","anon");//主页面登录
		map.put("/**/404","anon");//异常
		map.put("/**/user_register","anon");//用户注册
		map.put("/user_reg_saves","anon");//用户注册保存信息
		
		map.put("/**/reg_phone_repeat","anon");//用户注册保存信息
		map.put("/**/user_login","anon");//用户登录验证
		
		map.put("/**/user_page_list","anon");//分页查询数据 根据用户名字模糊查询，只有root权限用户才能进入
		// 登录页面
		shiroFilterFactoryBean.setLoginUrl("/login");
		// 认证成功跳转的页面
		shiroFilterFactoryBean.setSuccessUrl("/indexs");
		// 错误页面
		shiroFilterFactoryBean.setUnauthorizedUrl("/user_404");
		//设置过滤器链定义映射->setFilterChainDefinitionMap
		shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
		return shiroFilterFactoryBean;
	}

	// 加入注解的使用，不加入这个注解不生效
	///开启shiro aop注解支持
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}	
	//过滤器
	@Bean("permsFilter")
	public PermsFilter permsFilter() {
		return new PermsFilter();
	}
}
